home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
100 Great Games for Palm OS 2
/
PalmV2012301.ISO
/
action
/
The Same Game
/
same.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-26
|
23KB
|
857 lines
/*
Same - The Same Game for Palm Pilot
Copyright (C) 1998 Franτois Pessaux (francois.pessaux@inria.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <Common.h>
#include <System/SysAll.h>
#include <UI/UIAll.h>
#include "same.h"
#define SAME_APP_ID 'SaMe'
#define SAME_DB_TYPE 'Data'
#define SAME_STATE_DB_NAME "SameCurrent"
#define SAME_HISCORES_DB_NAME "SameHiScores"
#define MIN_SURFACE 1
#define BITS_WIDTH 16
#define BITS_HEIGHT 14
#define PATTERN_NUMBER 5
#define PATTERN_SIZE 10
#define Y_OFFSET (PATTERN_SIZE*2)
#define IS_MARKED(c) ((c) & 0x80)
#define SET_MARKED(c) ((c) = (c) | 0x80)
#define UNSET_MARKED(c) ((c) = (c) & 0x7F)
#define GET_COLOR(c) ((c) & 0x7F)
#define IS_EMPTY(c) ((c) == 0)
#define SET_EMPTY(c) ((c) = 0)
#define HS_SIZE 5
#define TRUE 1
#define FALSE 0
#define HISCORE_STD 0
#define HISCORE_CHALLENGE 1
/* Les autres valeurs sont la couleur choisie (sauf 0) */
#define CHALLENGE_GAME_UNDETERMINATED 0xFF
#define STANDARD_GAME 0xFE
/* White */
#define PATTERN1 {0x0000,0x0000,0x0000,0x0000}
/* Black */
#define PATTERN2 {0xFFFF,0xFFFF,0xFFFF,0xFFFF}
/* Dotted */
#define PATTERN3 {0xAA55,0xAA55,0xAA55,0xAA55}
/* Line black line white */
#define PATTERN4 {0x00FF, 0x00FF, 0x00FF, 0x00FF}
/* Grid */
#define PATTERN5 {0x55FF, 0x55FF, 0x55FF, 0x55FF}
/* Slanted line */
#define PATTERN6 {0x8142, 0x2418, 0x1824, 0x4281}
#define PATUNDEF {0x0000,0x0000,0x0000,0xFF00}
struct score_entry {
unsigned char name[6] ;
unsigned int score ;
};
struct score_entry hiscores[HS_SIZE+1] ;
unsigned char marked_surface ;
unsigned char remaining_cases ;
unsigned char current_color ;
unsigned char bits[BITS_WIDTH][BITS_HEIGHT] ;
unsigned int score ;
unsigned char score_text[10] ;
CustomPatternType pattern_array[PATTERN_NUMBER+1] = {
PATTERN1, PATTERN2, PATTERN3, PATTERN4, PATTERN5, PATTERN6 } ;
CustomPatternType undefined_challenge_pattern = PATUNDEF ;
unsigned char game_running = FALSE ;
unsigned char game_mode ;
void init_bits ()
{
char x, y ;
for (x = 0; x < BITS_WIDTH; x++) {
for (y = 0; y < BITS_HEIGHT; y++) {
bits[x][y] = (unsigned char) (SysRandom (0) % PATTERN_NUMBER) + 1 ;
}
}
/* Nombre de cases restant a effacer */
remaining_cases = BITS_WIDTH * BITS_HEIGHT ;
}
#define PUSH(v) stack[stackindex] = v ; stackindex++
#define POP(v) stackindex-- ; v = stack[stackindex]
/* Version ou on gere explicitement la recursion avec une pile a nous */
/* Pour avoir une version plus claire, mais non geree a la main, il */
/* faut aller voir dans le fichier "archive" */
/* On est oblige de faire ca pour eviter de faire peter la pile. Le */
/* schema de reursion (semble, car je ne l'ai pas prouve) garantit */
/* que la taille de la recursion est bornee par la taille de la piece. */
void mark_bits (char global_x_marking, char global_y_marking)
{
unsigned char switchvar ;
unsigned char stack[BITS_WIDTH * BITS_HEIGHT] ;
unsigned char stackindex=0 ;
PUSH (0) ;
begin:
switchvar = 5;
finish:
switch (switchvar) {
case 5:
SET_MARKED (bits[global_x_marking][global_y_marking]) ;
/* Il faudra verifier a la fin que la surface */
/* reellement marquee est superieure a 1 */
marked_surface++ ;
/* Maintenant, on regarde si chacun des voisins est de la couleur */
/* choisie pour l'effacement, s'il n'est pas deja marque comme a */
/* effacer, et si il se trouve bien dans la surface de jeu. Si */
/* c'est le cas, alors on recurse un coup. */
global_x_marking-- ;
if ((global_x_marking >= 0) &&
(GET_COLOR (bits[global_x_marking][global_y_marking])==current_color) &&
(!IS_MARKED (bits[global_x_marking][global_y_marking])))
{
PUSH (1) ;
goto begin ; /* mark_bits () ; */
}
case 1:
global_x_marking += 2 ;
if ((global_x_marking < BITS_WIDTH) &&
(GET_COLOR (bits[global_x_marking][global_y_marking])==current_color) &&
(!IS_MARKED (bits[global_x_marking][global_y_marking])))
{
PUSH (2) ;
goto begin ; /* mark_bits () ; */
}
case 2:
global_x_marking-- ;
global_y_marking-- ;
if ((global_y_marking >= 0) &&
(GET_COLOR (bits[global_x_marking][global_y_marking])==current_color) &&
(!IS_MARKED (bits[global_x_marking][global_y_marking])))
{
PUSH (3) ;
goto begin ; /* mark_bits () ; */
}
case 3:
global_y_marking += 2 ;
if ((global_y_marking < BITS_HEIGHT) &&
(GET_COLOR (bits[global_x_marking][global_y_marking])==current_color) &&
(!IS_MARKED (bits[global_x_marking][global_y_marking])))
{
PUSH (4) ;
goto begin ; /* mark_bits () ; */
}
case 4:
global_y_marking-- ;
POP (switchvar) ;
goto finish ;
}
}
void delete_bits (void)
{
char x, y, x2 ;
for (x = 0; x < BITS_WIDTH; x++) {
/* On traite les colonnes de gauche a droite */
char next_room = BITS_HEIGHT-1 ;
for (y = BITS_HEIGHT-1 ; y >= 0; y--) {
/* On traite chaque ligne du bas vers le haut */
if (IS_MARKED (bits[x][y])) {
/* La case est marquee, donc on la "vide" */
SET_EMPTY (bits[x][y]) ;
remaining_cases-- ;
}
else {
/* La case est a 0 (donc "vide"), donc par construction, */
/* les cases du dessus le sont aussi. Donc on peut passer */
/* a la colonne suivante */
if (IS_EMPTY (bits[x][y])) break ;
else {
/* La case n'est pas vide et n'est pas marquee */
unsigned char tmp = bits[x][y] ;
SET_EMPTY (bits[x][y]) ;
bits[x][next_room] = tmp ;
next_room-- ;
}
}
}
}
/* Maintenant, il faut scaner (de droite a gauche) les colonnes */
/* vides et les rapprocher a gauche pour faire du compactage */
for (x = BITS_WIDTH-1; x >= 0; x--) {
/* Si la case du bas est a 0, alors c'est que la colonne est vide */
if (IS_EMPTY (bits[x][BITS_HEIGHT-1])) {
/* x = indice de la colonne vide */
/* On rapproche toutes les colonnes se trouvant */
/* a droite en scanant de gauche a droite */
for (x2= x + 1; x2 < BITS_WIDTH ; x2++) {
if (x2 < BITS_WIDTH) {
/* La colonne x2 va dans colonne x2-1 et on */
/* efface le contenu de la colonne x2. */
for (y = 0; y < BITS_HEIGHT; y++) {
bits[x2-1][y] = bits[x2][y] ;
SET_EMPTY (bits[x2][y]) ;
}
}
}
}
}
}
void refresh_whole (void)
{
char x, y ;
RectangleType rect ;
for (y = 0; y < BITS_HEIGHT; y++) {
for (x = 0; x < BITS_WIDTH; x++) {
WinSetPattern (pattern_array[bits[x][y]]) ;
rect.topLeft.x = x * PATTERN_SIZE ;
rect.topLeft.y = (y * PATTERN_SIZE) + Y_OFFSET ;
rect.extent.x = PATTERN_SIZE ;
rect.extent.y = PATTERN_SIZE ;
WinFillRectangle (&rect, 0) ;
}
}
}
/* Hypothese, aucune cs n'est marquee lors de la verification */
Boolean check_game_over (void)
{
char x, y ;
for (x = 0; x < BITS_WIDTH-1; x++) {
for (y = BITS_HEIGHT-1; y > 0; y--) {
if (!IS_EMPTY (bits[x][y])) {
/* La cas n'est pas vide... */
if ((bits[x][y] == bits[x][y-1]) || (bits[x][y] == bits[x+1][y]))
return (FALSE) ;
}
else {
/* La case courante est vide, donc celles du dessus aussi */
/* donc on peut passer directement a la colonne suivante */
break ;
}
}
}
/* Si on arrive ici c'est qu'on n'a rien trouve et donc le jeu est fini */
return (TRUE) ;
}
void refresh_score (void)
{
StrIToA (score_text, score) ;
WinDrawChars (score_text, StrLen (score_text), 110, 0) ;
}
/* Part du principe qu'on est en mode challenge */
void refresh_challenge_indicator (void)
{
RectangleType rect ;
if (game_mode != CHALLENGE_GAME_UNDETERMINATED) {
/* Si le challenge est choisi, on indique le pattern choisi */
WinSetPattern (pattern_array[game_mode]) ;
}
else {
/* Met un petit truc indiquant que le challenge */
/* n'est pas encore choisi */
WinSetPattern (undefined_challenge_pattern) ;
}
rect.topLeft.x = 90 ;
rect.topLeft.y = 2 ;
rect.extent.x = PATTERN_SIZE ;
rect.extent.y = PATTERN_SIZE ;
WinFillRectangle (&rect, 0) ;
}
void handle_turn (char case_x, char case_y)
{
/* On verifie qu'on est bien dans l'espace de jeu et que la case */
/* designee n'est pas une case vide */
if ((case_x >= 0) && (case_x < BITS_WIDTH) &&
(case_y >= 0) && (case_y < BITS_HEIGHT) &&
(!IS_EMPTY (bits[case_x][case_y]))) {
/* Memorise la couleur actuellement pointee */
current_color = GET_COLOR (bits[case_x][case_y]) ;
if (game_mode == CHALLENGE_GAME_UNDETERMINATED) {
/* Fixe la couleur de challenge */
game_mode = current_color ;
refresh_challenge_indicator () ;
}
else {
/* Rien n'est marque a l'origine */
marked_surface = 0 ;
/* On fait le parcours de marquage */
mark_bits (case_x, case_y) ;
/* On met a jour le damier seulement s'il y a + d'1 composante connexe */
if (marked_surface > MIN_SURFACE) {
delete_bits () ;
if (game_mode == STANDARD_GAME)
score += ((marked_surface - 2) * (marked_surface - 2)) ;
else
{
/* On n'incremente le score que si la couleur est celle choisie */
if (game_mode == current_color)
score += ((marked_surface - 2) * (marked_surface - 2)) ;
}
refresh_whole () ;
refresh_score () ;
}
else {
/* En fait, la surface est trop petite, */
/* donc remettre la case en etat */
UNSET_MARKED (bits[case_x][case_y]) ;
}
}
}
}
int SortScore (struct score_entry *se1, struct score_entry *se2)
{
if (se1->score == se2->score) return (0) ;
if (se1->score < se2->score) return (1) ;
return (-1) ;
}
/* Charge les hiscores. Si la base n'existe pas, ca la cree */
void load_hiscore (unsigned which_one)
{
DmOpenRef same_db ;
LocalID db_id ;
UInt index ;
VoidPtr record ;
VoidHand handle ;
/* Memoriser les hiscores */
db_id = DmFindDatabase (0, SAME_HISCORES_DB_NAME ) ;
if (!db_id) {
/* La base n'existe pas. On la cree from scratch */
unsigned char i ;
/* On initialise donc le hiscores from scratch */
for (i=0;i<HS_SIZE;i++) {
StrCopy (hiscores[i].name, "-----") ;
hiscores[i].score = 0 ;
}
DmCreateDatabase (0, SAME_HISCORES_DB_NAME, SAME_APP_ID, SAME_DB_TYPE,
FALSE) ;
same_db = DmOpenDatabase (0, DmFindDatabase (0, SAME_HISCORES_DB_NAME),
dmModeReadWrite) ;
/* Hiscores en mode standard */
index = 0 ;
handle = DmNewRecord (same_db, &index,
HS_SIZE*sizeof(struct score_entry)) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)hiscores,
HS_SIZE*sizeof(struct score_entry)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
/* Hiscore en mode challenge */
index = 1 ;
handle = DmNewRecord (same_db, &index,
HS_SIZE*sizeof(struct score_entry)) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)hiscores,
HS_SIZE*sizeof(struct score_entry)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
DmCloseDatabase (same_db) ;
}
else {
/* Index des scores a charger en fonction du type demande */
if (which_one == HISCORE_STD) index = 0 ;
else index = 1 ;
/* On ouvre la base pour charger les anciens hiscores */
same_db = DmOpenDatabase (0, db_id, dmModeReadWrite) ;
handle = DmGetRecord (same_db, index) ;
record = MemHandleLock (handle) ;
MemMove ((VoidPtr)hiscores, (VoidPtr)record,
HS_SIZE * sizeof(struct score_entry)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
DmCloseDatabase (same_db) ;
}
}
void game_over (void)
{
/* Perfect Game */
if (remaining_cases == 0)
{
score += 1000 ;
FrmAlert (ALERT_PERFECT_ID) ;
}
game_running = FALSE ;
FrmAlert (ALERT_GOVER_ID) ;
if (game_mode == STANDARD_GAME) load_hiscore (HISCORE_STD) ;
else load_hiscore (HISCORE_CHALLENGE) ;
/* Demande le nom et calcule les hiscores par continuation si le score */
/* courant est superieur ou egal au plus bas score effectue */
if (score >= hiscores[HS_SIZE-1].score)
FrmPopupForm (NAME_FORM_ID) ;
}
Boolean HiScEventHandler (EventPtr event)
{
switch (event->eType)
{
case frmOpenEvent:
FrmDrawForm (FrmGetActiveForm ()) ;
/* Il faut afficher les scores */
{
unsigned char tmp_score_text[10] ;
unsigned i ;
for (i = 0; i < HS_SIZE; i++) {
WinDrawChars (hiscores[i].name, StrLen (hiscores[i].name),
20, 15+(i*10)) ;
StrIToA (tmp_score_text, hiscores[i].score) ;
WinDrawChars (tmp_score_text, StrLen (tmp_score_text),
50, 15+(i*10)) ;
}
}
return (TRUE) ;
break ;
case ctlSelectEvent:
FrmReturnToForm (0) ;
return (TRUE) ;
break ;
}
return (FALSE) ;
}
Boolean RuleEventHandler (EventPtr event)
{
switch (event->eType)
{
case frmOpenEvent:
FrmDrawForm (FrmGetActiveForm ()) ;
break ;
case ctlSelectEvent:
FrmReturnToForm (0) ;
break ;
}
return (FALSE) ;
}
Boolean NameEventHandler
(EventPtr event)
{
FormPtr form ;
switch (event->eType)
{
case frmOpenEvent:
form = FrmGetActiveForm () ;
FrmDrawForm(form) ;
FrmSetFocus (form, FrmGetObjectIndex (form, NAME_FIELD_ID)) ;
return (TRUE) ;
break ;
case ctlSelectEvent:
{
DmOpenRef same_db ;
UInt index ;
VoidPtr *record ;
VoidHand handle ;
CharPtr textptr ;
FieldPtr name_field ;
form = FrmGetActiveForm () ;
name_field = FrmGetObjectPtr (form,
FrmGetObjectIndex (form,
NAME_FIELD_ID)) ;
textptr = FldGetTextPtr (name_field) ;
if (textptr) StrCopy (hiscores[HS_SIZE].name, textptr) ;
else StrCopy (hiscores[HS_SIZE].name, "-----") ;
hiscores[HS_SIZE].score = score ;
/* Maintenant, on calcule la nouvelle liste de hiscores */
SysQSort (hiscores, HS_SIZE+1, sizeof (struct score_entry),
(CmpFuncPtr)SortScore, 0) ;
/* La base existe forcement deja */
same_db = DmOpenDatabase (0, DmFindDatabase (0, SAME_HISCORES_DB_NAME),
dmModeReadWrite) ;
/* On enregistre ces hiscores */
if (game_mode == STANDARD_GAME) index = 0 ;
else index = 1 ;
/* On recupere l'ancien record */
handle = DmGetRecord (same_db, index) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)hiscores,
HS_SIZE*sizeof(struct score_entry)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
DmCloseDatabase (same_db) ;
FrmReturnToForm (0) ;
/* Maintenant, on affiche les hiscores */
FrmPopupForm (HISCORE_FORM_ID) ;
return (TRUE) ;
}
break ;
}
return (FALSE) ;
}
Boolean MainEventHandler (EventPtr event)
{
switch (event->eType)
{
case frmOpenEvent:
FrmDrawForm (FrmGetActiveForm ()) ;
if (game_running) {
/* Il y a un jeu en cours, donc on l'affiche directement */
WinDrawChars (" ", 10, 110, 0) ;
refresh_whole () ;
/* Si on avait commence un challenge, il faut afficher */
/* quelle etait la couleur de ce dernier. */
if (game_mode != STANDARD_GAME) refresh_challenge_indicator () ;
refresh_score () ;
}
else {
/* Aucun jeu en cours. Donc page de presentation */
WinDrawInvertedChars ("The Same Game", 13, 43, 50) ;
WinDrawChars ("Written by", 10, 55, 70) ;
WinDrawChars ("Franτois Pessaux", 16, 42, 90) ;
WinDrawChars ("V 1.0", 5, 65, 110) ;
WinDrawChars ("Use menu to start", 17, 40, 145) ;
}
return (TRUE) ;
break ;
case penDownEvent:
if (game_running) {
handle_turn ((char) (event->screenX / PATTERN_SIZE),
(char) ((event->screenY - Y_OFFSET) /
PATTERN_SIZE)) ;
if (check_game_over ()) game_over () ;
}
return (TRUE) ;
break ;
case menuEvent:
switch (event->data.menu.itemID)
{
case MENUITEM_NEWGAME_ID:
{
RectangleType score_zone = { 110, 0, 50, 10 } ;
init_bits () ;
score = 0 ;
game_mode = STANDARD_GAME ;
game_running = TRUE ;
/* Efface la zone de score */
WinEraseRectangle (&score_zone, 0) ;
refresh_whole () ;
refresh_score () ;
/* Effacer le challenge indicator s'il y en avait un */
score_zone.topLeft.x = 90 ;
score_zone.topLeft.y = 2 ;
score_zone.extent.x = PATTERN_SIZE ;
score_zone.extent.y = PATTERN_SIZE ;
WinEraseRectangle (&score_zone, 0) ;
/* On verifie quand meme que le jeu n'est pas deja fini */
/* au cas ou la configuration generee serait vraiment pas */
/* fameuse et n'aurait pas, d'origine, de solution. */
if (check_game_over ()) game_over () ;
}
return (TRUE) ;
break ;
case MENUITEM_NEWCHALLENGE_ID:
{
RectangleType score_zone = { 110, 0, 50, 10 } ;
init_bits () ;
score = 0 ;
/* Le jeu est en mode challenge, mais la couleur n'a pas */
/* encore ete determinee */
game_mode = CHALLENGE_GAME_UNDETERMINATED ;
game_running = TRUE ;
/* Efface la zone de score */
WinEraseRectangle (&score_zone, 0) ;
refresh_whole () ;
refresh_score () ;
refresh_challenge_indicator () ;
/* On verifie quand meme que le jeu n'est pas deja fini */
/* au cas ou la configuration generee serait vraiment pas */
/* fameuse et n'aurait pas, d'origine, de solution. */
if (check_game_over ()) game_over () ;
}
return (TRUE) ;
break ;
case MENUITEM_ABOUT_ID:
FrmAlert (ALERT_INFO_ID) ;
return (TRUE) ;
break ;
case MENUITEM_STDHISCORE_ID:
load_hiscore (HISCORE_STD) ;
FrmPopupForm (HISCORE_FORM_ID) ;
return (TRUE) ;
break ;
case MENUITEM_CHALHISCORE_ID:
load_hiscore (HISCORE_CHALLENGE) ;
FrmPopupForm (HISCORE_FORM_ID) ;
return (TRUE) ;
break ;
case MENUITEM_RULE_ID:
FrmPopupForm (RULE_FORM_ID) ;
return (TRUE) ;
break ;
}
break ;
}
return (FALSE) ;
}
Boolean LoadCurrentGame (void)
{
DmOpenRef same_db ;
LocalID db_id ;
/* Chargement de la partie eventuellement en cours... A faire */
db_id = DmFindDatabase (0, SAME_STATE_DB_NAME) ;
if (db_id)
{
same_db = DmOpenDatabase (0, db_id, dmModeReadWrite) ;
if (same_db)
{
VoidPtr *record ;
VoidHand handle ;
/* Si la base existe, c'est qu'il y a un jeu en cours */
/* On charge le tableau en cours */
handle = DmGetRecord (same_db, 0) ;
record = MemHandleLock (handle) ;
MemMove ((unsigned char*)bits, (unsigned char*)record,
BITS_WIDTH*BITS_HEIGHT) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, 0, FALSE) ;
/* On charge le nombre de cases restant a supprimer */
handle = DmGetRecord (same_db, 1) ;
record = MemHandleLock (handle) ;
remaining_cases = *((unsigned char*)record) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, 1, FALSE) ;
/* On charge le score */
handle = DmGetRecord (same_db, 2) ;
record = MemHandleLock (handle) ;
score = *((unsigned int*)record) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, 2, FALSE) ;
/* On charge le mode de jeu */
handle = DmGetRecord (same_db, 3) ;
record = MemHandleLock (handle) ;
game_mode = *((unsigned char*)record) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, 3, FALSE) ;
/* Le jeu est donc en cours */
game_running = TRUE ;
DmCloseDatabase (same_db) ;
db_id = DmFindDatabase (0, SAME_STATE_DB_NAME) ;
DmDeleteDatabase (0, db_id) ;
/* On notifie qu'un jeu etait en cours */
return (TRUE) ;
}
}
/* On notifie quaucun jeu n'etait en cours */
return (FALSE) ;
}
void SaveCurrentGame ()
{
DmOpenRef same_db ;
VoidPtr record ;
VoidHand handle ;
UInt index ;
/* Cree la database en ecrasant l'eventuelle ancienne */
DmCreateDatabase (0, SAME_STATE_DB_NAME, SAME_APP_ID, SAME_DB_TYPE, FALSE) ;
/* Ouvre la database en lecture */
same_db = DmOpenDatabase (0, DmFindDatabase (0, SAME_STATE_DB_NAME),
dmModeReadWrite) ;
/* Alloue le record pour le tableau */
index = 0 ;
handle = DmNewRecord (same_db, &index, BITS_WIDTH*BITS_HEIGHT) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)bits, BITS_WIDTH*BITS_HEIGHT) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
/* Alloue le record pour le nombre de case restantes */
index = 1 ;
handle = DmNewRecord (same_db, &index, sizeof(unsigned char)) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)&remaining_cases, sizeof(unsigned char)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
/* Alloue le record pour le score */
index = 2 ;
handle = DmNewRecord (same_db, &index, sizeof(unsigned int)) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)&score, sizeof(unsigned int)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
/* Alloue le record pour le mode de jeu */
index = 3 ;
handle = DmNewRecord (same_db, &index, sizeof(unsigned char)) ;
record = MemHandleLock (handle) ;
DmWrite (record, 0, (VoidPtr*)&game_mode, sizeof(unsigned char)) ;
MemHandleUnlock (handle) ;
DmReleaseRecord (same_db, index, FALSE) ;
DmCloseDatabase (same_db) ;
}
void EventLoop (void)
{
EventType event ;
FormPtr form ;
int formID ;
short error ;
do {
EvtGetEvent (&event, -1) ;
if (SysHandleEvent (&event)) continue ;
if (MenuHandleEvent ((void *)0, &event, &error)) continue ;
if (event.eType == frmLoadEvent)
{
formID = event.data.frmLoad.formID ;
form = FrmInitForm (formID) ;
FrmSetActiveForm (form) ;
switch (formID)
{
case GAME_FORM_ID:
if (LoadCurrentGame ())
{
/* Il y avait un jeu en cours, donc on le lance directement */
game_running = TRUE ;
}
FrmSetEventHandler (form, (FormEventHandlerPtr) MainEventHandler) ;
break;
case HISCORE_FORM_ID:
FrmSetEventHandler (form, (FormEventHandlerPtr) HiScEventHandler) ;
break ;
case NAME_FORM_ID:
FrmSetEventHandler (form, (FormEventHandlerPtr) NameEventHandler) ;
break ;
case RULE_FORM_ID:
FrmSetEventHandler (form, (FormEventHandlerPtr) RuleEventHandler) ;
break ;
}
}
FrmDispatchEvent (&event) ;
} while (event.eType != appStopEvent) ;
/* Backup de l'etat de la partie s'il y a une partie en cours... */
if (game_running) SaveCurrentGame () ;
}
DWord PilotMain (Word cmd, Ptr cmdPBP, Word launchFlags)
{
if (cmd == sysAppLaunchCmdNormalLaunch)
{
FrmGotoForm (GAME_FORM_ID) ;
EventLoop () ;
}
return (0) ;
}